package com.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Set;

/**
 * @Author 咕唧
 * @Date 2022/7/5 22:24
 * @Version 1.0
 */
public class Nio07Server {
    public static void main(String[] args) throws Exception {
        //搞一个selector
        Selector selector = Selector.open();
        //搞一个server channel
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        //绑定端口
        socketChannel.bind(new InetSocketAddress("10.9.48.142", 12345));
        //设置为非阻塞
        socketChannel.configureBlocking(false);
        //注册到selector,并且关注accept
        socketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动了....");
        //循环
        while (true) {
            //首先我们要看看有没有事情发生,因为没有事情发生的话,没有必要继续做,
            //因为是阻塞的方法,所以有返回值的时候其实就代表有正常结果了,没有正常结果会一直阻塞,一直阻塞也就没有返回值
            int select = selector.select();
            //说明发生了我们感兴趣的事情
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            //遍历
            selectionKeys.forEach(selectionKey -> {
                //如果当前发生的是请求建立连接的事件
                if (selectionKey.isAcceptable()) {
                    //如果想要和客户端建立连接那就搞连接
                    //当前是哪个通道来的连接
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                    try {
                        //接受连接请求,一旦接受,连接就会建立完成
                        SocketChannel accept = serverSocketChannel.accept();
                        //设置为非阻塞
                        accept.configureBlocking(false);
                        System.out.println("有连接已经建立了" + accept.getLocalAddress());
                        //我们可以添加一个新的感兴趣的事情,接收数据,这次的通道是已经建立成功的通道
                        accept.register(selector, SelectionKey.OP_READ);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else if (selectionKey.isReadable()) {
                    try {
                        //有数据传递过来,可以读取数据了
                        SocketChannel channel = (SocketChannel) selectionKey.channel();
                        //开启读取数据空间
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        while (true) {
                            //先清理
                            byteBuffer.clear();
                            int  read = channel.read(byteBuffer);

                            if (read > 0) {
                                //翻转
                                byteBuffer.flip();
                                //读取里面的数据
                                String msg = String.valueOf(Charset.forName("gbk").decode(byteBuffer));
                                System.out.println("收到的数据:" + msg);
                                //我们可以选择回复数据
                                byteBuffer.rewind();
                                channel.write(byteBuffer);
                            } else {
                                System.out.println("没有数据了");
                                break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            });
            //清理已经发生的事情，等待下次事情发生
            selectionKeys.clear();

        }
    }
}
